from django.contrib.auth import logout
from django.contrib.auth.models import User
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.urls import reverse_lazy
from django.views.generic import CreateView, UpdateView, DeleteView, ListView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.utils import timezone
from django.db import transaction
from datetime import timedelta
from django.db.models import Q, Count, Avg
from django.http import JsonResponse
from django.contrib import messages
from django.core.paginator import Paginator

from .models import Book, BorrowRecord, Review, Author, Category, Publisher, UserProfile, Notification
from .forms import ReviewForm, BookSearchForm, UserProfileForm, BookForm, AuthorForm, CategoryForm, PublisherForm, BorrowRecordForm
from .recommendations import generate_recommendations
from .ai_services import get_book_summary


# --- 用户界面视图 ---

class UserBookListView(ListView):
    model = Book
    template_name = 'books/user_book_list.html'
    context_object_name = 'books'
    paginate_by = 12

    def get_queryset(self):
        queryset = Book.objects.select_related('author', 'category', 'publisher').all()
        
        # 处理搜索
        form = BookSearchForm(self.request.GET)
        if form.is_valid():
            query = form.cleaned_data.get('query')
            category = form.cleaned_data.get('category')
            author = form.cleaned_data.get('author')
            available_only = form.cleaned_data.get('available_only')
            
            if query:
                queryset = queryset.filter(
                    Q(title__icontains=query) |
                    Q(author__name__icontains=query) |
                    Q(isbn__icontains=query)
                )
            
            if category:
                queryset = queryset.filter(category=category)
            
            if author:
                queryset = queryset.filter(author=author)
            
            if available_only:
                queryset = queryset.filter(quantity__gt=0)
        
        return queryset.order_by('-created_at')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # 搜索表单
        context['search_form'] = BookSearchForm(self.request.GET)
        
        # 分类列表
        context['categories'] = Category.objects.all()
        
        # 热门图书
        context['popular_books'] = Book.objects.order_by('-borrow_count', '-view_count')[:6]
        
        # 最新图书
        context['new_books'] = Book.objects.order_by('-created_at')[:6]
        
        # 为登录用户生成个性化推荐
        if self.request.user.is_authenticated:
            context['recommendations'] = generate_recommendations(self.request.user)
            
        return context


@login_required
def borrow_book(request, book_id):
    book = get_object_or_404(Book, pk=book_id)
    
    # 检查用户是否可以借书
    profile, created = UserProfile.objects.get_or_create(user=request.user)
    if not profile.can_borrow_more():
        messages.error(request, f'您已达到最大借阅数量限制({profile.max_borrow_limit}本)')
        return redirect('book_detail', pk=book_id)
    
    if book.is_available():
        # 使用事务确保数据一致性
        with transaction.atomic():
            book.quantity -= 1
            book.borrow_count += 1
            book.save()
            # 设置30天后为到期日
            initial_due_date = timezone.now().date() + timedelta(days=30)
            BorrowRecord.objects.create(
                book=book,
                borrower=request.user,
                due_date=initial_due_date
            )
        messages.success(request, f'成功借阅《{book.title}》')
    else:
        messages.error(request, '该图书当前不可借')
    
    return redirect('book_detail', pk=book_id)


class MyBooksListView(LoginRequiredMixin, ListView):
    model = BorrowRecord
    template_name = 'books/my_books.html'
    context_object_name = 'borrow_records'

    def get_queryset(self):
        # 只返回当前用户未归还的图书记录
        return BorrowRecord.objects.filter(
            borrower=self.request.user, 
            return_date__isnull=True
        ).select_related('book', 'book__author').order_by('-borrow_date')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # 用户档案
        profile, created = UserProfile.objects.get_or_create(user=self.request.user)
        context['profile'] = profile
        
        # 借阅统计
        total_borrowed = BorrowRecord.objects.filter(borrower=self.request.user).count()
        total_returned = BorrowRecord.objects.filter(
            borrower=self.request.user, 
            return_date__isnull=False
        ).count()
        overdue_count = BorrowRecord.objects.filter(
            borrower=self.request.user,
            return_date__isnull=True,
            due_date__lt=timezone.now().date()
        ).count()
        
        context['stats'] = {
            'total_borrowed': total_borrowed,
            'total_returned': total_returned,
            'overdue_count': overdue_count,
        }
        
        return context


@login_required
def return_book(request, record_id):
    record = get_object_or_404(BorrowRecord, pk=record_id, borrower=request.user)
    if not record.return_date:
        with transaction.atomic():
            record.return_date = timezone.now()
            record.save()
            record.book.quantity += 1
            record.book.save()
        messages.success(request, f'成功归还《{record.book.title}》')
    return redirect('my_books')


@login_required
def renew_loan(request, record_id):
    record = get_object_or_404(BorrowRecord, pk=record_id, borrower=request.user)
    if record.renewals_left > 0 and not record.return_date:
        record.due_date += timedelta(days=15) # 续借15天
        record.renewals_left -= 1
        record.save()
        messages.success(request, f'成功续借《{record.book.title}》')
    else:
        messages.error(request, '无法续借，请检查续借次数或图书状态')
    return redirect('my_books')


@login_required
def user_profile(request):
    """用户档案页面"""
    profile, created = UserProfile.objects.get_or_create(user=request.user)
    
    if request.method == 'POST':
        form = UserProfileForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
            messages.success(request, '档案更新成功')
            return redirect('user_profile')
    else:
        form = UserProfileForm(instance=profile)
    
    # 借阅历史
    borrow_history = BorrowRecord.objects.filter(
        borrower=request.user
    ).select_related('book', 'book__author').order_by('-borrow_date')[:10]
    
    context = {
        'profile': profile,
        'form': form,
        'borrow_history': borrow_history,
    }
    return render(request, 'books/user_profile.html', context)


# --- 管理员界面视图 ---
class StaffRequiredMixin(LoginRequiredMixin, UserPassesTestMixin):
    def test_func(self):
        return self.request.user.is_staff

    def handle_no_permission(self):
        return redirect('login')


class DashboardView(StaffRequiredMixin, ListView):
    """管理员仪表板"""
    template_name = 'books/manage/dashboard.html'
    context_object_name = 'recent_borrows'
    
    def get_queryset(self):
        return BorrowRecord.objects.select_related('book', 'borrower').order_by('-borrow_date')[:10]
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # 统计信息
        total_books = Book.objects.count()
        total_users = User.objects.count()
        total_borrows = BorrowRecord.objects.count()
        active_borrows = BorrowRecord.objects.filter(return_date__isnull=True).count()
        overdue_borrows = BorrowRecord.objects.filter(
            return_date__isnull=True,
            due_date__lt=timezone.now().date()
        ).count()
        
        context['stats'] = {
            'total_books': total_books,
            'total_users': total_users,
            'total_borrows': total_borrows,
            'active_borrows': active_borrows,
            'overdue_borrows': overdue_borrows,
        }
        
        # 热门图书
        context['popular_books'] = Book.objects.order_by('-borrow_count')[:5]
        
        # 逾期记录
        context['overdue_records'] = BorrowRecord.objects.filter(
            return_date__isnull=True,
            due_date__lt=timezone.now().date()
        ).select_related('book', 'borrower')[:5]
        
        return context


class ManageBookListView(StaffRequiredMixin, ListView):
    model = Book
    template_name = 'books/manage/book_list.html'
    context_object_name = 'books'
    paginate_by = 20

    def get_queryset(self):
        queryset = Book.objects.select_related('author', 'category', 'publisher').all()
        
        # 搜索功能
        query = self.request.GET.get('q')
        if query:
            queryset = queryset.filter(
                Q(title__icontains=query) |
                Q(author__name__icontains=query) |
                Q(isbn__icontains=query)
            )
        
        return queryset.order_by('-created_at')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['search_query'] = self.request.GET.get('q', '')
        return context


class BookCreateView(StaffRequiredMixin, CreateView):
    model = Book
    form_class = BookForm
    template_name = 'books/manage/book_form.html'
    success_url = reverse_lazy('manage_book_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '图书添加成功')
        return response


class BookUpdateView(StaffRequiredMixin, UpdateView):
    model = Book
    form_class = BookForm
    template_name = 'books/manage/book_form.html'
    success_url = reverse_lazy('manage_book_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '图书更新成功')
        return response


class BookDeleteView(StaffRequiredMixin, DeleteView):
    model = Book
    template_name = 'books/manage/book_confirm_delete.html'
    success_url = reverse_lazy('manage_book_list')

    def delete(self, request, *args, **kwargs):
        messages.success(request, '图书删除成功')
        return super().delete(request, *args, **kwargs)


# --- 添加下面的登出视图 ---
def logout_view(request):
    logout(request)
    return redirect('user_book_list')


class BookDetailView(DetailView):
    model = Book
    template_name = 'books/book_detail.html'
    context_object_name = 'book'

    def get_object(self):
        obj = super().get_object()
        # 增加浏览次数
        obj.increment_view_count()
        return obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        book = self.get_object()
        
        # 获取所有书评
        context['reviews'] = book.reviews.select_related('user').all()
        
        # 如果用户已登录，检查他是否已评论过
        user_has_reviewed = False
        if self.request.user.is_authenticated:
            if book.reviews.filter(user=self.request.user).exists():
                user_has_reviewed = True
        
        context['user_has_reviewed'] = user_has_reviewed
        
        # 只有当用户登录了且尚未评论时，才向模板传递评论表单
        if self.request.user.is_authenticated and not user_has_reviewed:
            context['review_form'] = ReviewForm()
        
        # 相关图书推荐
        if book.category:
            context['related_books'] = Book.objects.filter(
                category=book.category
            ).exclude(id=book.id)[:4]
        
        # 检查用户是否已借阅此书
        if self.request.user.is_authenticated:
            context['user_has_borrowed'] = BorrowRecord.objects.filter(
                book=book,
                borrower=self.request.user,
                return_date__isnull=True
            ).exists()
            
        return context

    def post(self, request, *args, **kwargs):
        # 只有登录用户才能提交 POST 请求
        if not request.user.is_authenticated:
            return redirect('login')

        book = self.get_object()
        form = ReviewForm(request.POST)

        if form.is_valid():
            # 先不保存到数据库，因为需要补充 user 和 book 信息
            review = form.save(commit=False)
            review.book = book
            review.user = request.user
            review.save()
            
            # 触发表模型的更新方法，重新计算平均分
            book.update_rating()
            
            messages.success(request, '评论提交成功')
            # 成功后重定向回详情页
            return redirect('book_detail', pk=book.pk)
        else:
            # 如果表单无效，重新渲染页面，并把无效的表单(含错误信息)传回去
            context = self.get_context_data()
            context['review_form'] = form
            return self.render_to_response(context)


@login_required
def generate_summary_view(request, pk):
    if request.method == 'GET':
        book = get_object_or_404(Book, pk=pk)
        summary = get_book_summary(book.title, book.author)
        return JsonResponse({'summary': summary})
    return JsonResponse({'error': 'Invalid request method'}, status=405)


class BorrowedBooksListView(StaffRequiredMixin, ListView):
    model = BorrowRecord
    template_name = 'books/manage/borrowed_list.html'
    context_object_name = 'records'
    paginate_by = 20

    def get_queryset(self):
        # 使用 select_related 优化查询，一次性获取关联的 book 和 borrower 信息，避免 N+1 查询问题
        queryset = BorrowRecord.objects.select_related('book', 'borrower').order_by('-borrow_date')
        
        # 过滤功能
        status = self.request.GET.get('status')
        if status:
            if status == 'overdue':
                queryset = queryset.filter(
                    return_date__isnull=True,
                    due_date__lt=timezone.now().date()
                )
            elif status == 'active':
                queryset = queryset.filter(return_date__isnull=True)
            elif status == 'returned':
                queryset = queryset.filter(return_date__isnull=False)
        
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['status_filter'] = self.request.GET.get('status', '')
        return context


# --- 作者管理视图 ---
class AuthorListView(StaffRequiredMixin, ListView):
    model = Author
    template_name = 'books/manage/author_list.html'
    context_object_name = 'authors'
    paginate_by = 15

    def get_queryset(self):
        queryset = Author.objects.all()
        query = self.request.GET.get('q')
        if query:
            queryset = queryset.filter(name__icontains=query)
        return queryset.order_by('name')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['search_query'] = self.request.GET.get('q', '')
        return context


class AuthorCreateView(StaffRequiredMixin, CreateView):
    model = Author
    form_class = AuthorForm
    template_name = 'books/manage/author_form.html'
    success_url = reverse_lazy('author_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '作者添加成功')
        return response


class AuthorUpdateView(StaffRequiredMixin, UpdateView):
    model = Author
    form_class = AuthorForm
    template_name = 'books/manage/author_form.html'
    success_url = reverse_lazy('author_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '作者信息更新成功')
        return response


class AuthorDeleteView(StaffRequiredMixin, DeleteView):
    model = Author
    template_name = 'books/manage/author_confirm_delete.html'
    success_url = reverse_lazy('author_list')

    def delete(self, request, *args, **kwargs):
        messages.success(request, '作者删除成功')
        return super().delete(request, *args, **kwargs)


# --- 分类管理视图 ---
class CategoryListView(StaffRequiredMixin, ListView):
    model = Category
    template_name = 'books/manage/category_list.html'
    context_object_name = 'categories'
    paginate_by = 15


class CategoryCreateView(StaffRequiredMixin, CreateView):
    model = Category
    form_class = CategoryForm
    template_name = 'books/manage/category_form.html'
    success_url = reverse_lazy('category_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '分类添加成功')
        return response


class CategoryUpdateView(StaffRequiredMixin, UpdateView):
    model = Category
    form_class = CategoryForm
    template_name = 'books/manage/category_form.html'
    success_url = reverse_lazy('category_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '分类更新成功')
        return response


class CategoryDeleteView(StaffRequiredMixin, DeleteView):
    model = Category
    template_name = 'books/manage/category_confirm_delete.html'
    success_url = reverse_lazy('category_list')

    def delete(self, request, *args, **kwargs):
        messages.success(request, '分类删除成功')
        return super().delete(request, *args, **kwargs)


# --- 出版社管理视图 ---
class PublisherListView(StaffRequiredMixin, ListView):
    model = Publisher
    template_name = 'books/manage/publisher_list.html'
    context_object_name = 'publishers'
    paginate_by = 15


class PublisherCreateView(StaffRequiredMixin, CreateView):
    model = Publisher
    form_class = PublisherForm
    template_name = 'books/manage/publisher_form.html'
    success_url = reverse_lazy('publisher_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '出版社添加成功')
        return response


class PublisherUpdateView(StaffRequiredMixin, UpdateView):
    model = Publisher
    form_class = PublisherForm
    template_name = 'books/manage/publisher_form.html'
    success_url = reverse_lazy('publisher_list')

    def form_valid(self, form):
        response = super().form_valid(form)
        messages.success(self.request, '出版社信息更新成功')
        return response


class PublisherDeleteView(StaffRequiredMixin, DeleteView):
    model = Publisher
    template_name = 'books/manage/publisher_confirm_delete.html'
    success_url = reverse_lazy('publisher_list')

    def delete(self, request, *args, **kwargs):
        messages.success(request, '出版社删除成功')
        return super().delete(request, *args, **kwargs)


# --- 统计报表视图 ---
@login_required
def statistics_view(request):
    """数据统计视图"""
    # ... (其他统计)

    # 按分类统计图书数量
    category_stats = Category.objects.annotate(
    ).order_by('-num_books')
    
    # 基础统计
    total_books = Book.objects.count()
    total_users = User.objects.count()
    total_borrows = BorrowRecord.objects.count()
    active_borrows = BorrowRecord.objects.filter(return_date__isnull=True).count()
    
    # 分类统计
    category_stats = Category.objects.annotate(
        book_count=Count('books')
    ).order_by('-book_count')
    
    # 热门图书
    popular_books = Book.objects.order_by('-borrow_count')[:10]
    
    # 热门作者
    popular_authors = Author.objects.annotate(
        book_count=Count('books'),
        total_borrows=Count('books__borrowrecords')
    ).order_by('-total_borrows')[:10]
    
    # 月度借阅统计
    monthly_stats = []
    for i in range(6):
        month = timezone.now().date() - timedelta(days=30*i)
        count = BorrowRecord.objects.filter(
            borrow_date__year=month.year,
            borrow_date__month=month.month
        ).count()
        monthly_stats.append({
            'month': month.strftime('%Y-%m'),
            'count': count
        })
    monthly_stats.reverse()
    
    context = {
        'total_books': total_books,
        'total_users': total_users,
        'total_borrows': total_borrows,
        'active_borrows': active_borrows,
        'category_stats': category_stats,
        'popular_books': popular_books,
        'popular_authors': popular_authors,
        'monthly_stats': monthly_stats,
    }
    
    return render(request, 'books/manage/statistics.html', context)


# views.py
from django.db.models import Count
from .models import YourModel  # 替换为你的模型名


def statistics_view(request):
    # 使用annotate动态创建num_books字段
    queryset = YourModel.objects.annotate(
        num_books=Count('book')  # 使用你的实际关联字段名
    )

    # 现在可以安全地使用num_books进行过滤或排序
    # queryset = queryset.order_by('-num_books')

    context = {'data': queryset}
    return render(request, 'your_template.html', context)